package ucd.csi.comp30220.fall2011.oteop.airline.impl;

import java.io.IOException;
import java.util.Date;
import java.util.Map;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

import ucd.csi.comp30220.fall2011.oteop.OTEOP;
import ucd.csi.comp30220.fall2011.oteop.airline.Airline;
import ucd.csi.comp30220.fall2011.oteop.airline.AirlineInfo;
import ucd.csi.comp30220.fall2011.oteop.flight.FlightInfo;
import ucd.csi.comp30220.fall2011.oteop.util.PortFinder;

public class AirlineServer {
    
    private int port;
    private JmDNS jmDNS;
    private ServiceInfo serviceInfo;
    private AirlineImpl airline;
    private Server server;
    
    public AirlineServer(AirlineInfo info, FlightInfo[] flightInfos) throws Exception {
        airline = new AirlineImpl(info, flightInfos);
        port = PortFinder.getNextAvailable();
        server = new Server(port);
        server.setHandler(new AbstractHandler() {
            public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
                    throws IOException, ServletException {
                response.setContentType("text/html;charset=utf-8");
                baseRequest.setHandled(true);
                try {
                    if ("GET".equals(request.getMethod())) {
                        response.getWriter().println(stringifyInfo());
                    }
                    else if ("PUT".equals(request.getMethod())) {
                        dispatch(request.getParameterMap());
                        response.setStatus(HttpServletResponse.SC_OK);
                    }
                    else {
                        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
                    response.getWriter().println(e.getMessage());
                }
                response.flushBuffer();
            }
        });
        server.start();
        jmDNS = JmDNS.create();
        serviceInfo = ServiceInfo.create(
            OTEOP.JMDNS_TYPE_TCP_LOCAL, 
            info.getCode(), 
            Airline.JMDNS_SUB_TYPE, 
            port, 
            info.getName());
        jmDNS.registerService(serviceInfo);
        airline.start();
        System.err.println("Registered: " +info +" on " +port);
    }
    
    public void stop() throws Exception {
        server.stop();
    }
    
    private String stringifyInfo() throws Exception {
        return airline.getInfo().getCode() + "|" + airline.getInfo().getName(); 
    }

    private void dispatch(Map<String,String[]> parameters) throws Exception {
        String method = parameters.get("method")[0];
        if ("flightDeparted".equals(method)) {
            airline.flightDeparted(
                parameters.get("flightNumber")[0], 
                parameters.get("airportCode")[0], 
                new Date(Long.parseLong(parameters.get("dateTime")[0])));
        }
        else if ("flightLanded".equals(method)) {
            airline.flightLanded(
                parameters.get("flightNumber")[0], 
                parameters.get("airportCode")[0], 
                new Date(Long.parseLong(parameters.get("dateTime")[0])));
        }
        else
            throw new Exception("Unknown method [" +method +"]");
    }
}
